﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace CodePlex.PropertyDesigner
{
    public class PropertyDesignerControlModel : ViewModel
    {
        public PropertyDesignerControlModel(ClassDesignerData data)
        {
            Data = data;
            Nodes = new ObservableCollection<PropertyDesignerControlPropertyNodeModel>();
            foreach (var property in data.Properties)
                Nodes.Add(new PropertyDesignerControlPropertyNodeModel(property));
        }

        public ClassDesignerData Data
        {
            get { return GetProperty<ClassDesignerData>("Data"); }
            set { SetProperty("Data", value); }
        }

        public ObservableCollection<PropertyDesignerControlPropertyNodeModel> Nodes
        {
            get;
            private set;
        }
    }

    public class PropertyDesignerControlPropertyNodeModel : ViewModel
    {
        public PropertyDesignerControlPropertyNodeModel(PropertyDesignerData data)
        {
            Data = data;

            Nodes = new ObservableCollection<PropertyDesignerControlPropertyAttributeNodeModel>
                        {
                            new PropertyDesignerControlPropertyAttributeNodeModel("AccessModifier", data.AccessModifier),
                            new PropertyDesignerControlPropertyAttributeNodeModel("InheritanceModifier", data.InheritanceModifier),
                            new PropertyDesignerControlPropertyAttributeNodeModel("EqualityCheck", data.EqualityCheck)
                        };
        }

        public PropertyDesignerData Data
        {
            get { return GetProperty<PropertyDesignerData>("Data"); }
            set { SetProperty("Data", value);}
        }

        public ObservableCollection<PropertyDesignerControlPropertyAttributeNodeModel> Nodes
        {
            get;
            private set;
        }
    }

    public class PropertyDesignerControlPropertyAttributeNodeModel : ViewModel
    {
        public PropertyDesignerControlPropertyAttributeNodeModel(string name, object value)
        {
            Name = name;
            Value = value;
        }
        
        public string Name
        {
            get { return GetProperty<string>("Name"); }
            private set { SetProperty("Name", value); }
        }

        public object Value
        {
            get { return GetProperty<object>("Value"); }
            set { SetProperty("Value", value); }
        }
    }

    public abstract class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        
        protected void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        protected void SetProperty<T>(string name, T value)
        {
            var oldValue = GetProperty<T>(name);
            if (Equals(oldValue, value))
                return;
            _properties[name] = value;
            RaisePropertyChanged(name);
        }

        protected T GetProperty<T>(string name, T @default = default(T))
        {
            object value;
            if (!_properties.TryGetValue(name, out value))
                return @default;
            return (T) value;
        }

        private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();
    }

    public class PropertyDesignerControlModelSample : PropertyDesignerControlModel
    {
        public PropertyDesignerControlModelSample() : base(new ClassDesignerDataSample())
        {
        }
    }
}
